package com.bblocks.filter;


import cn.hutool.extra.servlet.ServletUtil;
import com.bblocks.util.ServletUtils;
import jodd.io.StreamUtil;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 *  controller 重复获取到 RequestBody过滤器
 *  目前只保留ajax请求
 *  需：@ServletComponentScan(basePackages = "com.bblocks") ，确保启用
 */
@WebFilter(value = "/*", filterName = "ajaxRequestBodyKeepFilter")
public class AjajxRequestBodyKeepFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        ServletRequest requestWrapper = null;
        if(request instanceof HttpServletRequest && ServletUtils.isAjaxRequest(request)) {
            requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request);
        }


        //System.out.println("====>结束OAuthFilter doFilterInternal过滤器====");
		if(requestWrapper != null)
			filterChain.doFilter(requestWrapper, response);
		else
			filterChain.doFilter(request, response);
    }


	class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {

		private final byte[] body;

		public BodyReaderHttpServletRequestWrapper(HttpServletRequest request)
				throws IOException {
			super(request);

			//body = StreamUtil.readBytes(request.getReader(), JoddDefault.encoding);
			body = ServletUtil.getBodyBytes(request);
		}

		@Override
		public BufferedReader getReader() throws IOException {
			return new BufferedReader(new InputStreamReader(getInputStream()));
		}

		@Override
		public ServletInputStream getInputStream() throws IOException {
			//final ByteArrayInputStream bais = new ByteArrayInputStream(body);

			return new CachedServletInputStream(body) ;
		}


		public class CachedServletInputStream extends ServletInputStream {
			private final ByteArrayInputStream input;

			public CachedServletInputStream(byte[] body) {
				// create a new input stream from the cached request body
				input = new ByteArrayInputStream(body);
			}

			@Override
			public boolean isFinished() {
				return false;
			}

			@Override
			public boolean isReady() {
				return false;
			}

			@Override
			public void setReadListener(ReadListener readListener) {

			}

			@Override
			public int read() throws IOException {
				return input.read();
			}
		}
	}

}


